package org.dormi.learn.product.application.material;

import org.dormi.learn.primitive.Measure;
import org.dormi.learn.primitive.MeasureUnitEnum;
import org.dormi.learn.product.domain.material.entity.Material;
import org.dormi.learn.product.domain.material.entity.MaterialLogistics;
import org.dormi.learn.product.domain.material.entity.PhysicalForm;
import org.dormi.learn.product.domain.material.entity.TrackingTypeEnum;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;
import org.mapstruct.factory.Mappers;

import java.math.BigDecimal;

/**
 * dto - entity 之间的转换
 *
 * @author : dormi330
 * @version : 1.0
 */
@Mapper
interface MaterialAssembler {

    MaterialAssembler MAPPER = Mappers.getMapper(MaterialAssembler.class);

    /* === eo -> dto === */
    /* === eo -> dto === */
    /* === eo -> dto === */
    @Mapping(source = "formCode", target = "physicalForm", qualifiedByName = "physicalForm")
    @Mapping(source = "dto", target = "logistics", qualifiedByName = "logistics")
    @Mapping(source = "dto", target = "validityTime", qualifiedByName = "validityTime")
    @Mapping(source = "minSkuCode", target = "minSKU", qualifiedByName = "minSKU")
    @Mapping(source = "trackingTypeCode", target = "trackingType", qualifiedByName = "trackingType")
    Material toEO(MaterialCreateInDTO dto);

    @Named("physicalForm")
    default PhysicalForm physicalForm(String code) {
        return PhysicalForm.findValue(code);
    }

    @Named("logistics")
    default MaterialLogistics logistics(MaterialCreateInDTO dto) {
        MaterialLogistics l = new MaterialLogistics();
        if (null != dto.getLengthUnitCode()) {
            l.setLength(dto.getLength());
            l.setWidth(dto.getWidth());
            l.setHeigth(dto.getHeigth());
            l.setLengthUnit(MeasureUnitEnum.findValue(dto.getLengthUnitCode()));
        }

        if (null != dto.getWeightUnitCode()) {
            l.setNetWeight(dto.getNetWeight());
            l.setGrossWeight(dto.getGrossWeight());
            l.setWeightUnit(MeasureUnitEnum.findValue(dto.getWeightUnitCode()));
        }

        return l.effective() ? l : null;
    }


    @Named("validityTime")
    default Measure validityTime(MaterialCreateInDTO dto) {
        if (null == dto.getValidityUnitCode() || null == dto.getValidityTimeLength()) {
            return null;
        } else {
            Measure m = new Measure();
            MeasureUnitEnum unit = MeasureUnitEnum.findValue(dto.getValidityUnitCode());
            m.setUnit(unit);
            m.setQuantity(dto.getValidityTimeLength());
            return m;
        }
    }

    @Named("minSkuCode")
    default MeasureUnitEnum minSkuCode(String code) {
        return MeasureUnitEnum.findValue(code);
    }

    @Named("trackingType")
    default TrackingTypeEnum trackingType(String code) {
        return TrackingTypeEnum.findValue(code);
    }


    /* === dto -> eo === */
    /* === dto -> eo === */
    /* === dto -> eo === */
    @Mapping(source = "physicalForm", target = "formCode", qualifiedByName = "formCode")
    @Mapping(source = "logistics", target = "length", qualifiedByName = "length")
    @Mapping(source = "logistics", target = "width", qualifiedByName = "width")
    @Mapping(source = "logistics", target = "heigth", qualifiedByName = "heigth")
    @Mapping(source = "logistics", target = "lengthUnitCode", qualifiedByName = "lengthUnitCode")
    @Mapping(source = "logistics", target = "netWeight", qualifiedByName = "netWeight")
    @Mapping(source = "logistics", target = "grossWeight", qualifiedByName = "grossWeight")
    @Mapping(source = "logistics", target = "weightUnitCode", qualifiedByName = "weightUnitCode")
    @Mapping(source = "validityTime", target = "validityTimeLength", qualifiedByName = "validityTimeLength")
    @Mapping(source = "validityTime", target = "validityUnitCode", qualifiedByName = "validityUnitCode")
    @Mapping(source = "minSKU", target = "minSkuCode", qualifiedByName = "minSkuCode")
    @Mapping(source = "trackingType", target = "trackingTypeCode", qualifiedByName = "trackingTypeCode")
    MaterialDTO toDTO(Material eo);

    @Named("formCode")
    default String formCode(PhysicalForm form) {
        return form == null ? null : form.getCode();
    }

    @Named("length")
    default BigDecimal length(MaterialLogistics l) {
        return l == null ? null : l.getLength();
    }

    @Named("width")
    default BigDecimal width(MaterialLogistics l) {
        return l == null ? null : l.getWidth();
    }

    @Named("heigth")
    default BigDecimal heigth(MaterialLogistics l) {
        return l == null ? null : l.getHeigth();
    }

    @Named("lengthUnitCode")
    default String lengthUnitCode(MaterialLogistics l) {
        return l == null ? null : l.getLengthUnit().getCode();
    }

    @Named("netWeight")
    default BigDecimal netWeight(MaterialLogistics l) {
        return l == null ? null : l.getNetWeight();
    }

    @Named("grossWeight")
    default BigDecimal grossWeight(MaterialLogistics l) {
        return l == null ? null : l.getGrossWeight();
    }

    @Named("weightUnitCode")
    default String weightUnitCode(MaterialLogistics l) {
        return l == null ? null : l.getWeightUnit().getCode();
    }

    @Named("validityTimeLength")
    default BigDecimal validityTimeLength(Measure v) {
        return v == null ? null : v.getQuantity();
    }

    @Named("validityUnitCode")
    default String weightUnitCode(Measure v) {
        return v == null ? null : v.getUnit().getCode();
    }

    @Named("minSkuCode")
    default String minSkuCode(MeasureUnitEnum v) {
        return v == null ? null : v.getCode();
    }

    @Named("trackingTypeCode")
    default String trackingTypeCode(TrackingTypeEnum t) {
        return t == null ? null : t.getCode();
    }
}

